#include <kernel.h>

struct auto_stack
{
    uint32_t r0;
    uint32_t r1;
    uint32_t r2;
    uint32_t r3;
    uint32_t r12;
    uint32_t lr;
    uint32_t pc;
    uint32_t psr;
};

struct stack
{
    /* r4 ~ r11 register */
    uint32_t r4;
    uint32_t r5;
    uint32_t r6;
    uint32_t r7;
    uint32_t r8;
    uint32_t r9;
    uint32_t r10;
    uint32_t r11;

    struct auto_stack auto_stack;
};

uint32_t thread_from, thread_to;
uint32_t thread_switch_flag;

uint8_t *stack_init(void *entry, void *parameter, void *stack_addr, void *exit)
{
    struct stack *stack;
    uint8_t *sp;
    
    sp = (uint8_t *)__align_down((uint32_t)stack_addr, 8);
    sp -= sizeof(struct stack);
    
    stack = (struct stack *)sp;
    
    for (int i = 0; i < 8; ++i)
        ((uint32_t *)stack)[i] = 0xabcdabcd;
    
    stack->auto_stack.r0 = (ubase_t)parameter;
    stack->auto_stack.r1 = 0;
    stack->auto_stack.r2 = 0;
    stack->auto_stack.r3 = 0;
    stack->auto_stack.r12 = 0;
    stack->auto_stack.lr = (ubase_t)exit;
    stack->auto_stack.pc = (ubase_t)entry;
    stack->auto_stack.psr = 0x01000000;
    
    return sp;
}
